package com.link.base.base.message.push.service;

import cn.jiguang.common.ClientConfig;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import com.link.base.base.message.push.dao.mybatis.mapper.PushMapper;
import com.link.base.base.message.push.model.PushInfo;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.cllog.LCLogger;
import com.link.core.util.RedisUtil;
import javax.annotation.Resource;
import com.link.core.util.StringUtils;
import com.link.core.util.redisclient.LinkRedisClient;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * app消息推送
 * 
 * @author ouyangzhenqiang
 * @date 2018/10/26
 */
@Component
public class JpushServiceImpl {
    private static String HUAWEI = "HUAWEI";
    private static String OPPO = "OPPO";
    private static String MEIZU = "MEIZU";
    private static String XIAOMI = "XIAOMI";
    private static String VIVO = "VIVO";
    @Resource
    private PushMapper pushMapper;
    @Resource
    private HuaweiPushServiceImpl huaweiPushService;
    @Resource
    private  MeizuPushServiceImpl meizuPushService;
    @Resource
    private XiaomiPushServiceImpl xiaomiPushService;
    @Resource
    private VivoPushServiceImpl vivoPushService;
    @Resource
    private OppoPushServiceImpl oppoPushService;
    
    /**
     * 构造消息对象
     * 
     * @author ouyangzhenqiang
     * @date 2018/10/26
     * @param item PushInfo
     */
    private static PushPayload buildPushObject_all_all_alert(PushInfo item) {
        String module = StringUtils.isBlank(item.getModule()) ? "push" : item.getModule();
        String objectIdStr = item.getObjectId() == null ? "none" : item.getObjectId() + "";
        return PushPayload.newBuilder()
                .setPlatform(Platform.all())
                .setAudience(Audience.registrationId(item.getToken()))
                .setNotification(Notification.newBuilder()
                        .addPlatformNotification(AndroidNotification.newBuilder()
                                .addExtra("module", module)
                                .addExtra("objectId", objectIdStr)
                                .setTitle(item.getPushTitle())
                                .setAlert(item.getPushNote())
                                .build())
                        .addPlatformNotification(IosNotification.newBuilder()
                                .addExtra("module", module)
                                .addExtra("objectId", objectIdStr)
                                .setAlert(item.getPushNote())
                                .setSound("happy")
                                .build())
                        .build())
                .setOptions(Options.newBuilder()
                        // true-推送生产环境 false-推送开发环境（测试使用参数）
                        .setApnsProduction(true)
                        // 消息在JPush服务器的失效时间（测试使用参数）
                        .setTimeToLive(90)
                        .build())
                .build();
    }
    
    /**
     * 基于appId从Redis中获取极光推送的key&master，基于key&master创建连接
     * 
     * @author ouyangzhenqiang
     * @date 2018/10/26
     * @param busAppId 应用Id
     */
    private JPushClient getClient(String busAppId) {
        String redisKey = "APP_PUSH_CONFIG";
        LinkRedisClient j = null;
        try {
            j = RedisUtil.getJedis();
            String key = j.hget(redisKey, "jpushAppKey_" + busAppId);
            String master = j.hget(redisKey, "jpushMasterSecret_" + busAppId);
            JPushClient jpushClient = new JPushClient(master, key, null, ClientConfig.getInstance());
            return jpushClient;
        } finally {
            RedisUtil.returnResource(j);
        }
    }

    /**
     * 发送消息 - 支持提醒和立即发送
     *
     * @author ouyangzhenqiang
     * @date 2019/07/25 17:31
     */
    void jPush(PushInfo record) throws Exception {
        verifyPushInfo(record);
        // 极光token
        String jPushToken = record.getToken();
        // 手机厂商
        String pushServiceType = record.getPushServiceType();
        // 手机厂商推送token
        String pushServiceToken = record.getPushServiceToken();
        if (StringUtils.isNotBlank(pushServiceToken)) {
            if (HUAWEI.equals(pushServiceType)) {
                huaweiPushService.hwPush(record);
            } else if (XIAOMI.equals(pushServiceType)) {
                xiaomiPushService.xiaomiPush(record);
            } else if (MEIZU.equals(pushServiceType)) {
                meizuPushService.meizuPush(record);
            } else if (VIVO.equals(pushServiceType)) {
                vivoPushService.vivoPush(record);
            } else if (OPPO.equals(pushServiceType)) {
                oppoPushService.oppoPush(record);
            } else {
                throw new BasicServiceException("未匹配到【" + pushServiceType + "】手机厂商推送渠道！");
            }
        } else if (StringUtils.isNotBlank(jPushToken)) {
            JPushClient jpushClient = getClient(record.getAppId());
            PushPayload payload = buildPushObject_all_all_alert(record);
            PushResult result = jpushClient.sendPush(payload);
            LCLogger.info().withMessageKey("jpush").withMessage("sendPush result -> " + result).flush();
        } else {
            throw new BasicServiceException("极光token与手机厂商渠道token均为空，无法处理消息！");
        }
    }

    /**
     * 用于定时工作流
     *
     * @author ouyangzhenqiang
     * @date 2018/10/26
     * @param list
     */
    public void jpushList(List<PushInfo> list) throws Exception {
        LinkRedisClient j = null;
        try {
            String redisKey = "APP_PUSH_CONFIG";
            j = RedisUtil.getJedis();
            String jpushErrorNum = j.hget(redisKey, "jpushErrorNum");
            for (PushInfo item : list) {
                String pushType = item.getPushServiceType();
                if (StringUtils.isBlank(pushType)) {
                    // 用户未绑定设备时，标记为PUSH，反之为正常的pushType
                    pushType = "PUSH";
                }
                try {
                    jPush(item);
                } catch (Exception e) {
                    LCLogger.withException(e);
                    String failNum = item.getAppFailNum();
                    int num = Integer.parseInt(failNum) + 1;
                    int numJpushErr = Integer.parseInt(jpushErrorNum);
                    if (num > numJpushErr) {
                        item.setAppDealFlag("Y");
                    } else {
                        item.setAppDealFlag("N");
                    }
                    item.setAppFailNum(num + "");
                    item.setAppDealMsg("[" + pushType + "]" + e.getMessage());
                    pushMapper.updateAppPushResult(item);
                    continue;
                }
                item.setAppDealFlag("Y");
                item.setAppDealMsg("[" + pushType + "]" + "推送成功!");
                pushMapper.updateAppPushResult(item);
            }
        } catch (Exception e) {
            LCLogger.withException(e);
            throw new BasicServiceException("推送异常: " + e.getMessage());
        } finally {
            RedisUtil.returnResource(j);
        }
    }

    /**
     * 校验推送消息、设备信息
     *
     * @author ouyangzhenqiang
     * @date 2018/10/26
     * @param pushInfo
     */
    private void verifyPushInfo(PushInfo pushInfo) throws BasicServiceException {
        if (StringUtils.isBlank(pushInfo.getPushNote())) {
            throw new BasicServiceException("推送内容不能为空！");
        }
        if (StringUtils.isBlank(pushInfo.getAppId())) {
            throw new BasicServiceException("未匹配到消息用户对应的移动设备！");
        }
    }

}
